const express = require('express');
const cors = require('cors');
const path = require('path');
const plcService = require('./plc-service');

const app = express();
const PORT = 3002; // PLC服务使用不同的端口

// 中间件
app.use(cors());
app.use(express.json());

// 注意：已移除严格的访问控制中间件，所有API端点现在都可以直接访问
// 如需重新启用，请取消下面代码的注释
/*
app.use('/api/plc/read', strictAccessControl);
app.use('/api/plc/write', strictAccessControl);
app.use('/api/plc/read-group', strictAccessControl);
app.use('/api/plc/write-group', strictAccessControl);
*/

// 提供静态文件服务（用于访问PLC配置文件）
app.use(express.static(path.join(__dirname, '../public')));

// 添加严格的访问控制中间件 - 只允许队列服务访问PLC操作API
function strictAccessControl(req, res, next) {
  // 检查请求来源
  const origin = req.get('Origin') || '';
  const referer = req.get('Referer') || '';
  const userAgent = req.get('User-Agent') || '';
  
  console.log('🔐 访问控制检查:');
  console.log('  - 路径:', req.path);
  console.log('  - Origin:', origin);
  console.log('  - Referer:', referer);
  console.log('  - User-Agent:', userAgent);
  console.log('  - IP:', req.ip);
  
  // 允许的来源：队列服务(localhost:3003)
  const isFromQueueService = (
    origin.includes('localhost:3003') || 
    referer.includes('localhost:3003') ||
    userAgent.includes('queue-service')
  );
  
  console.log('  - 是否来自队列服务:', isFromQueueService);
  
  // 如果来自队列服务，则允许访问
  if (isFromQueueService) {
    console.log('  ✅ 访问允许');
    next();
  } else {
    console.log('  ❌ 访问拒绝');
    res.status(403).json({ 
      error: 'Forbidden', 
      message: 'PLC操作只能通过队列服务进行访问',
      allowed_sources: 'Queue Service (localhost:3003)',
      your_request: {
        origin: origin,
        referer: referer,
        user_agent: userAgent,
        ip: req.ip,
        path: req.path
      }
    });
  }
}

// 添加浮点数精度处理函数
function processFloatPrecision(values) {
  if (!values || typeof values !== 'object') {
    return values;
  }
  
  const processedValues = {};
  for (const [key, value] of Object.entries(values)) {
    if (typeof value === 'number') {
      // 检查是否为整数
      if (Number.isInteger(value)) {
        processedValues[key] = value;
      } else {
        // 对于浮点数，保留6位小数并去除尾部的0
        processedValues[key] = parseFloat(value.toFixed(6));
      }
    } else {
      processedValues[key] = value;
    }
  }
  return processedValues;
}

// 添加队列和规则引擎集成
const http = require('http');

// 直接读取PLC变量接口（重定向到标准读取接口，因为已移除权限控制）
app.post('/api/plc/read-direct', async (req, res) => {
  try {
    const { variables } = req.body;
    console.log('📥 收到直接PLC读取请求(重定向到标准接口):', variables);
    
    // 由于已移除权限控制，直接调用标准读取逻辑
    // 检查PLC连接状态
    if (!plcService.isConnected) {
      console.error('❌ PLC未连接，无法读取变量');
      return res.status(400).json({ error: 'PLC未连接', message: '请先连接PLC再进行读取操作' });
    }
    
    const values = await plcService.readVariables(variables);
    // 处理浮点数精度
    const processedValues = processFloatPrecision(values);
    
    console.log('✅ 直接PLC读取成功(重定向):', processedValues);
    res.json({ success: true, values: processedValues });
  } catch (err) {
      console.error('❌ 直接PLC读取失败:', err);
      // 确保总是返回一个有效的错误消息
      const errorMessage = err.message || JSON.stringify(err) || '未知错误';
      res.status(500).json({ error: '读取失败', message: errorMessage });
    }
});

// 获取分组配置 - 新增API
app.get('/api/plc/groups', async (req, res) => {
  try {
    // 确保分组配置已加载
    if (!plcService.getGroups()) {
      await plcService.loadGroups();
    }
    res.json({ success: true, groups: plcService.getGroups() });
  } catch (err) {
    console.error('获取PLC分组配置失败:', err);
    res.status(500).json({ error: '获取分组配置失败', message: err.message });
  }
});

// 手动加载所有分组配置 - 新增API
app.post('/api/plc/load-groups', async (req, res) => {
  try {
    console.log('🔄 正在手动加载所有分组配置...');
    const groups = await plcService.loadAllGroups();
    res.json({ success: true, groups });
  } catch (err) {
    console.error('手动加载PLC分组配置失败:', err);
    res.status(500).json({ error: '加载分组配置失败', message: err.message });
  }
});

// 手动加载指定分组配置 - 新增API
app.post('/api/plc/load-group', async (req, res) => {
  try {
    const { groupId } = req.body;
    console.log(`🔄 正在手动加载分组配置: ${groupId}`);
    const group = await plcService.loadGroupFile(groupId);
    res.json({ success: true, group });
  } catch (err) {
    console.error('手动加载PLC分组配置失败:', err);
    res.status(500).json({ error: '加载分组配置失败', message: err.message });
  }
});

// 获取分组文件列表 - 新增API
app.get('/api/plc/group-files', async (req, res) => {
  try {
    console.log('🔄 正在获取分组文件列表...');
    const files = await plcService.loadGroupFiles();
    res.json({ success: true, files });
  } catch (err) {
    console.error('获取分组文件列表失败:', err);
    res.status(500).json({ error: '获取分组文件列表失败', message: err.message });
  }
});

// 发送变量更新到规则引擎 - 新增功能
function sendVariableUpdateToRulesEngine(variables) {
  const rulesEngineUrl = 'http://localhost:3004/api/variables';
  
  const data = JSON.stringify({
    variables: variables
  });
  
  const options = {
    hostname: 'localhost',
    port: 3004,
    path: '/api/variables',
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Content-Length': data.length
    }
  };
  
  const req = http.request(options, (res) => {
    console.log(`📊 规则引擎响应状态: ${res.statusCode}`);
  });
  
  req.on('error', (error) => {
    console.error('❌ 发送到规则引擎失败:', error.message);
  });
  
  req.write(data);
  req.end();
}

app.post('/api/plc/read', async (req, res) => {
  try {
    const { variables } = req.body;
    
    // 检查PLC连接状态
    if (!plcService.isConnected) {
      console.error('❌ PLC未连接，无法读取变量');
      return res.status(400).json({ error: 'PLC未连接', message: '请先连接PLC再进行读取操作' });
    }
    
    // 通过统一队列处理读取请求
    const values = await plcService.readVariables(variables);
    // 处理浮点数精度
    const processedValues = processFloatPrecision(values);
    
    // 发送变量更新到规则引擎
    sendVariableUpdateToRulesEngine(processedValues);
    
    res.json({ success: true, values: processedValues });
  } catch (err) {
    console.error('读取PLC变量失败:', err);
    res.status(500).json({ error: '读取失败', message: err.message });
  }
});

// 读取指定分组的变量 - 新增API
app.post('/api/plc/read-group', async (req, res) => {
  try {
    const { groupId } = req.body;
    
    // 检查PLC连接状态
    if (!plcService.isConnected) {
      console.error('❌ PLC未连接，无法读取分组变量');
      return res.status(400).json({ error: 'PLC未连接', message: '请先连接PLC再进行读取操作' });
    }
    
    // 通过统一队列处理分组读取请求
    const values = await plcService.readGroupVariables(groupId);
    console.log('📤 分组读取API返回:', { groupId, values });
    // 处理浮点数精度
    const processedValues = processFloatPrecision(values);
    res.json({ success: true, groupId, values: processedValues });
  } catch (err) {
    console.error('读取PLC分组变量失败:', err);
    res.status(500).json({ error: '读取分组变量失败', message: err.message });
  }
});

// 读取所有分组的变量 - 新增API
app.get('/api/plc/read-all-groups', async (req, res) => {
  try {
    // 检查PLC连接状态
    if (!plcService.isConnected) {
      console.error('❌ PLC未连接，无法读取所有分组变量');
      return res.status(400).json({ error: 'PLC未连接', message: '请先连接PLC再进行读取操作' });
    }
    
    // 直接处理所有分组读取请求（这个操作比较重，不通过队列）
    const allResults = await plcService.readAllGroupVariables();
    console.log('📤 所有分组读取API返回:', allResults);
    // 处理浮点数精度
    const processedResults = {};
    for (const [groupId, groupData] of Object.entries(allResults)) {
      if (groupData.data) {
        processedResults[groupId] = {
          ...groupData,
          data: processFloatPrecision(groupData.data)
        };
      } else {
        processedResults[groupId] = groupData;
      }
    }
    res.json({ success: true, results: processedResults });
  } catch (err) {
    console.error('读取所有PLC分组变量失败:', err);
    res.status(500).json({ error: '读取所有分组变量失败', message: err.message });
  }
});

app.post('/api/plc/write', async (req, res) => {
  try {
    const { name, value } = req.body;
    console.log('📥 收到PLC写入请求:', name, '值:', value);
    
    // 检查PLC连接状态
    if (!plcService.isConnected) {
      console.error('❌ PLC未连接，无法写入变量');
      return res.status(400).json({ error: 'PLC未连接', message: '请先连接PLC再进行写入操作' });
    }
    
    // 通过统一队列处理写入请求
    const result = await plcService.writeVariable(name, value);
    console.log('✅ PLC变量写入成功:', name, '返回结果:', result);
    // 确保返回完整的成功响应
    res.json({ success: true, message: '写入成功', result });
  } catch (err) {
    console.error('❌ 写入PLC变量失败:', err);
    res.status(500).json({ error: '写入失败', message: err.message });
  }
});

// 写入分组中的变量 - 新增API
app.post('/api/plc/write-group', async (req, res) => {
  try {
    const { groupId, variableName, value } = req.body;
    console.log('📥 收到PLC分组写入请求:', groupId, variableName, '值:', value);
    
    // 检查PLC连接状态
    if (!plcService.isConnected) {
      console.error('❌ PLC未连接，无法写入变量');
      return res.status(400).json({ error: 'PLC未连接', message: '请先连接PLC再进行写入操作' });
    }
    
    // 通过统一队列处理分组写入请求
    const result = await plcService.writeGroupVariable(groupId, variableName, value);
    console.log('✅ PLC分组变量写入成功:', groupId, variableName, '返回结果:', result);
    res.json({ success: true, message: '写入成功', result });
  } catch (err) {
    console.error('❌ 写入PLC分组变量失败:', err);
    res.status(500).json({ error: '写入分组变量失败', message: err.message });
  }
});

app.post('/api/plc/connect', async (req, res) => {
  try {
    const { config } = req.body;
    const connected = await plcService.init(config);
    res.json({ success: connected, connected });
  } catch (err) {
    console.error('连接PLC失败:', err);
    res.status(500).json({ error: '连接失败', message: err.message });
  }
});

app.post('/api/plc/disconnect', (req, res) => {
  try {
    plcService.disconnect();
    res.json({ success: true });
  } catch (err) {
    console.error('断开PLC连接失败:', err);
    res.status(500).json({ error: '断开连接失败', message: err.message });
  }
});

// 获取PLC状态 - 增强版API
app.get('/api/plc/status', (req, res) => {
  try {
    const status = plcService.getConnectionStatus ? 
      plcService.getConnectionStatus() : 
      { isConnected: plcService.isConnected, hasConnector: !!plcService.connector };
    
    res.json({ 
      success: true, 
      connected: status.isConnected,
      connectorConnected: status.connectorConnected,
      hasConnector: status.hasConnector,
      reconnectAttempts: status.reconnectAttempts || 0,
      service: 'PLC Service'
    });
  } catch (err) {
    console.error('获取PLC状态失败:', err);
    res.status(500).json({ error: '获取状态失败', message: err.message });
  }
});

// 重新连接PLC - 新增API
app.post('/api/plc/reconnect', async (req, res) => {
  try {
    console.log('📥 收到PLC重新连接请求');
    const reconnected = plcService.reconnect ? 
      await plcService.reconnect() : 
      await plcService.init();
    
    res.json({ success: reconnected, connected: reconnected });
  } catch (err) {
    console.error('PLC重新连接失败:', err);
    res.status(500).json({ error: '重新连接失败', message: err.message });
  }
});

// 获取PLC连接详细信息 - 新增API
app.get('/api/plc/connection-details', (req, res) => {
  try {
    const connectionStatus = plcService.getConnectionStatus ? 
      plcService.getConnectionStatus() : 
      { isConnected: plcService.isConnected };
    
    res.json({ 
      success: true, 
      connectionStatus,
      config: plcService.getConfig() 
    });
  } catch (err) {
    console.error('获取PLC连接详情失败:', err);
    res.status(500).json({ error: '获取连接详情失败', message: err.message });
  }
});

// 获取PLC配置 - 新增API
app.get('/api/plc/config', async (req, res) => {
  try {
    // 确保配置已加载
    if (!plcService.getConfig()) {
      await plcService.loadConfig();
    }
    res.json({ success: true, config: plcService.getConfig() });
  } catch (err) {
    console.error('获取PLC配置失败:', err);
    res.status(500).json({ error: '获取配置失败', message: err.message });
  }
});

// 保存PLC配置 - 新增API
app.post('/api/plc/save-config', async (req, res) => {
  try {
    const { config } = req.body;
    console.log('📥 收到PLC配置保存请求');
    console.log('📥 配置内容:', JSON.stringify(config, null, 2));
    const result = await plcService.saveConfig(config);
    console.log('📤 保存配置结果:', result);
    if (result.success) {
      res.json({ success: true, message: '配置保存成功', result });
    } else {
      res.status(400).json({ success: false, error: '保存配置失败', message: result.message });
    }
  } catch (err) {
    console.error('❌ 保存PLC配置失败:', err);
    res.status(500).json({ success: false, error: '保存配置失败', message: err.message });
  }
});

// 保存分组配置 - 新增API
app.post('/api/plc/save-group-config', async (req, res) => {
  try {
    const { groupId, groupConfig } = req.body;
    console.log(`📥 收到分组配置保存请求: ${groupId}`);
    console.log(`📥 分组配置内容:`, JSON.stringify(groupConfig, null, 2));
    const result = await plcService.saveGroupConfig(groupId, groupConfig);
    console.log('📤 保存分组配置结果:', result);
    if (result.success) {
      res.json({ success: true, message: '分组配置保存成功', result });
    } else {
      res.status(400).json({ success: false, error: '保存分组配置失败', message: result.message });
    }
  } catch (err) {
    console.error('❌ 保存分组配置失败:', err);
    res.status(500).json({ success: false, error: '保存分组配置失败', message: err.message });
  }
});

// 另存为分组配置 - 新增API
app.post('/api/plc/save-as-group-config', async (req, res) => {
  try {
    const { groupId, groupConfig } = req.body;
    console.log(`📥 收到分组配置另存为请求: ${groupId}`);
    console.log(`📥 分组配置内容:`, JSON.stringify(groupConfig, null, 2));
    const result = await plcService.saveAsGroupConfig(groupId, groupConfig);
    console.log('📤 另存为分组配置结果:', result);
    if (result.success) {
      res.json({ success: true, message: '分组配置另存为成功', result });
    } else {
      res.status(400).json({ success: false, error: '另存为分组配置失败', message: result.message });
    }
  } catch (err) {
    console.error('❌ 另存为分组配置失败:', err);
    res.status(500).json({ success: false, error: '另存为分组配置失败', message: err.message });
  }
});

// 删除分组配置 - 新增API
app.delete('/api/plc/delete-group-config', async (req, res) => {
  try {
    const { groupId } = req.body;
    console.log(`📥 收到分组配置删除请求: ${groupId}`);
    const result = await plcService.deleteGroupConfig(groupId);
    console.log('📤 删除分组配置结果:', result);
    if (result.success) {
      res.json({ success: true, message: '分组配置删除成功', result });
    } else {
      res.status(400).json({ success: false, error: '删除分组配置失败', message: result.message });
    }
  } catch (err) {
    console.error('❌ 删除分组配置失败:', err);
    res.status(500).json({ success: false, error: '删除分组配置失败', message: err.message });
  }
});

// 健康检查
app.get('/api/health', (req, res) => {
  res.json({ 
    status: 'OK', 
    service: 'PLC Service',
    timestamp: new Date().toISOString(),
    connected: plcService.isConnected
  });
});

// 获取PLC内部队列状态 - 新增API
app.get('/api/plc/queue-status', (req, res) => {
  try {
    const queueStatus = plcService.getQueueStatus ? 
      plcService.getQueueStatus() : 
      { queueLength: 0, processing: false, pendingTasks: [] };
    
    res.json({ 
      success: true, 
      queueStatus
    });
  } catch (err) {
    console.error('获取PLC队列状态失败:', err);
    res.status(500).json({ error: '获取队列状态失败', message: err.message });
  }
});

// 获取PLC内部队列历史记录 - 新增API
app.get('/api/plc/queue-history', (req, res) => {
  try {
    const queueHistory = plcService.getQueueHistory ? 
      plcService.getQueueHistory() : 
      [];
    
    res.json({ 
      success: true, 
      queueHistory
    });
  } catch (err) {
    console.error('获取PLC队列历史记录失败:', err);
    res.status(500).json({ error: '获取队列历史记录失败', message: err.message });
  }
});

// 启动PLC服务
app.listen(PORT, () => {
  console.log(`🚀 PLC服务运行在端口 ${PORT}`);
  console.log(`📡 API基础URL: http://localhost:${PORT}/api`);
  
  // 启动时自动尝试连接PLC
  console.log('🔄 启动时自动连接PLC...');
  plcService.init().then(connected => {
    if (connected) {
      console.log('✅ PLC服务启动成功并已连接');
      
      // 如果配置了周期性读取，确保它已启动
      if (plcService.getConfig && plcService.getConfig().variables && plcService.getConfig().readInterval) {
        const variables = plcService.getConfig().variables.map(v => v.name);
        const interval = plcService.getConfig().readInterval;
        console.log(`📊 配置了 ${variables.length} 个变量的周期性读取，间隔: ${interval}ms`);
      }
    } else {
      console.warn('⚠️ PLC服务启动成功，但未连接到PLC');
      console.log('🔄 自动重连机制已启动，将在可用时尝试连接');
    }
  }).catch(err => {
    console.error('❌ 启动时初始化PLC失败:', err);
    console.log('🔄 自动重连机制已启动，将在可用时尝试连接');
  });
});

module.exports = app;